package com.cool.shark.service.Impl;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.cool.shark.ex.ServiceException;
import com.cool.shark.mapper.GoodsMapper;
import com.cool.shark.pojo.dto.GoodsDto;
import com.cool.shark.pojo.dto.GoodsStandardDto;
import com.cool.shark.pojo.entity.Goods;
import com.cool.shark.pojo.vo.*;
import com.cool.shark.service.GoodsService;
import com.cool.shark.utils.UploadGiteeImgBedUtils;
import com.cool.shark.web.ServiceCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @Name: GoodsServiceImpl
 * @Author: 西风残叶
 * @Date: 2024/4/17 20:37
 * @Version: 1.0
 * @TODO: 商品的业务实现类
 */
@Service
@Slf4j
public class GoodsServiceImpl implements GoodsService {
    @Autowired
    private GoodsMapper mapper;

    /**
     * 插入商品信息
     *
     * @param goodsDto 商品数据传输对象，包含商品的详细信息
     */
    @Override
    public void insert(GoodsDto goodsDto) {
        log.info("开始处理添加商品业务,参数{}", goodsDto);
        if (goodsDto == null) {
            String msg = "添加商品失败,商品数据不能为空";
            throw new ServiceException(ServiceCode.ERR_BAD_REQUEST, msg);
        }
        if (goodsDto.getTitle() == null) {
            String msg = "添加商品失败,商品名称不能为空";
            throw new ServiceException(ServiceCode.ERR_BAD_REQUEST, msg);
        }
        if (goodsDto.getStock() <0) {
            String msg = "添加商品失败,商品库存不能小于0";
            throw new ServiceException(ServiceCode.ERR_BAD_REQUEST, msg);
        }
        if (goodsDto.getImg() == null) {
            String msg = "添加商品失败,商品图片不能为空";
            throw new ServiceException(ServiceCode.ERR_BAD_REQUEST, msg);
        }
        if (goodsDto.getPrice() <= 0){
            String msg = "添加商品失败,商品价格不能小于0";
            throw new ServiceException(ServiceCode.ERR_BAD_REQUEST, msg);
        }
        Goods goods = new Goods();
        BeanUtils.copyProperties(goodsDto, goods);
        goods.setSpuId(System.currentTimeMillis());
        int insert = mapper.insert(goods);
        if (insert != 1) {
            String msg = "添加商品失败,服务器忙,请稍后重试!";
            throw new ServiceException(ServiceCode.ERR_INSERT_FAILED, msg);
        }
    }

    /**
     * 列出所有商品信息
     * 本方法不接受参数，调用后会返回商品列表。
     */
    @Override
    public List<GoodsVo> list() {
        log.info("开始处理列出所有商品业务");
        List<GoodsVo> list = mapper.list();
        Iterator<GoodsVo> iterator = list.iterator();
        while (iterator.hasNext()) {
            GoodsVo next = iterator.next();
            if (next.getEnable()!=1){
                iterator.remove();
            }
        }
        log.info("即将返回数据:{}", list);
        return list;
    }

    @Override
    public List<GoodsVo> listAll() {
        log.info("开始处理列出所有商品业务");
        List<GoodsVo> listAll = mapper.list();
        return listAll;
    }

    /**
     * 使某个对象启用。
     *
     * @param spuId 对象的唯一标识符。
     */
    @Override
    public void setEnable(Long spuId) {
        updateEnableByspuId(spuId, 1);
    }

    /**
     * 使某个对象禁用。
     *
     * @param spuId 对象的唯一标识符。
     */
    @Override
    public void setDisable(Long spuId) {
        updateEnableByspuId(spuId, 0);
    }

    /**
     * 上传商品图片
     *
     * @param multipartFile 多部分文件，代表要上传的图片
     * @return 返回上传成功后的图片URL
     */
    @Override
    public String uploadGoodsImg(MultipartFile multipartFile) throws IOException {
        // 检查上传的文件是否存在
        String originalFilename = multipartFile.getOriginalFilename();
        // 生成目标URL，用于后续的文件上传
        String targetURL = UploadGiteeImgBedUtils.createGoodsUploadFileUrl(originalFilename);
        log.info("目标url：" + targetURL);

        // 将文件内容封装到请求体中
        Map<String, Object> uploadBodyMap = UploadGiteeImgBedUtils.getUploadBodyMap(multipartFile.getBytes());

        // 发起POST请求上传文件
        String JSONResult = HttpUtil.post(targetURL, uploadBodyMap);

        // 解析上传响应的JSON字符串
        JSONObject jsonObj = JSONUtil.parseObj(JSONResult);

        // 判断上传请求是否成功
        if (jsonObj == null || jsonObj.getObj("commit") == null) {
            return "请求失败";
        }

        // 获取并返回图片的下载地址
        JSONObject content = JSONUtil.parseObj(jsonObj.getObj("content"));
        Object downloadUrl = content.getObj("download_url");
        log.info("下载地址：" + downloadUrl);
        return downloadUrl.toString();
    }

    /**
     * 删除商品相关信息。
     *
     * @param spuId 包含商品删除信息的DTO（数据传输对象），具体包括需要删除的商品ID等信息。
     */
    @Override
    public void delete(Long spuId) {
        log.info("即将根据spuId:{}删除商品信息", spuId);
        int delete = mapper.delete(spuId);
        if (delete != 1){
            String msg = "删除商品失败,服务器忙,请稍后重试!";
            throw new ServiceException(ServiceCode.ERR_DELETE_FAILED, msg);
        }
        log.info("删除商品信息成功");
    }

    /**
     * 根据SPU ID获取商品信息。
     *
     * @param spuId 商品的SPU（Standard Product Unit）ID，用于标识唯一商品。
     * @return 返回对应SPU ID的商品信息VO（Value Object），包含商品的各种详细信息。
     */
    @Override
    public GoodsStandardVo getGoodsBySpuId(Long spuId) {
        log.info("即将根据spuId:{}获取商品信息", spuId);
        GoodsStandardVo select = mapper.getGoodsStandard(spuId);
        return select;
    }

    /**
     * 更新商品标准信息。
     *
     * @param goodsDto 商品标准数据传输对象，包含需要更新的商品标准信息。
     *                 通过此对象，可以更新商品的各个属性，例如名称、规格等。
     *                 注意：该方法不会返回任何值，更新操作的结果（例如成功或失败）应该通过其他方式（例如日志）进行跟踪。
     */
    @Override
    public void update(GoodsStandardDto goodsDto) {
        log.info("开始处理修改业务,参数:{}",goodsDto);
        int update = mapper.updateStandard(goodsDto);
        if (update!=1){
            String msg = "修改失败,服务器忙!";
            throw new ServiceException(ServiceCode.ERR_UPDATE_FAILED, msg);
        }
        log.info("修改成功");
    }

    /**
     * 获取商品详情信息
     *
     * @param id 商品的唯一标识符
     * @return 返回一个GoodsDetailVo对象，包含商品的详细信息
     */
    @Override
    public GoodsDetailVo getGoodsDetail(Long id) {
        log.info("开始查询商品详情,参数:{}",id);
        GoodsDetailVo goodsDetailVo = mapper.getGoodsDetail(id);
        return goodsDetailVo;
    }

    /**
     * 获取商品数量列表。
     *
     * <p>该方法不接受任何参数，返回一个包含商品数量信息的列表。
     * 列表中的每个元素都代表一个商品及其对应的数量。
     *
     * @return List<GoodsNumVo> - 商品数量列表。每个列表项都包含商品的详细信息和数量。
     */
    @Override
    public List<GoodsNumVo> getGoodsNum() {
        List<GoodsNumVo> goodsNum = mapper.getGoodsNum();
        log.info("数据为:{}",goodsNum);
        return goodsNum;
    }

    /**
     * 根据关键字搜索商品信息。
     *
     * @param keyword 搜索关键字，用于匹配商品名称或描述。
     * @return 返回一个商品信息列表，包含与关键字匹配的商品。
     */
    @Override
    public List<GoodsVo> search(String keyword) {
        if (keyword.trim()==null||keyword.trim().isEmpty()){
            String msg = "搜索失败,请输入关键字!";
            throw new ServiceException(ServiceCode.ERR_BAD_REQUEST, msg);
        }
        List<GoodsVo> search = mapper.search(keyword);
        Iterator<GoodsVo> iterator = search.iterator();
        while (iterator.hasNext()){
            GoodsVo next = iterator.next();
            if (next.getStock()==0){
                iterator.remove();
            }
        }
        return search;
    }

    /**
     * 获取商品销售情况的列表。
     *
     * <p>该方法不接受任何参数，返回一个包含商品销售信息的列表。
     * 列表中的每个元素都是GoodsSalesVO类型，代表一个商品的销售记录。
     *
     * @return List<GoodsSalesVO> 返回一个包含商品销售信息的列表。
     */
    @Override
    public List<GoodsSalesVO> sales() {
        log.info("即将获取商品销售情况");
        List<GoodsSalesVO> sales = mapper.sales();
        return sales;
    }

    /**
     * 根据轮播图ID查询关联的商品列表。
     *
     * @param carouselId 轮播图的唯一标识符，用于查询与之关联的商品信息。
     * @return 返回一个商品信息列表，这些商品与指定的轮播图相关联。
     */
    @Override
    public List<GoodsResultVo> listByCarouselId(Long carouselId) {
        log.info("即将根据轮播图ID:{}查询关联的商品列表",carouselId);
        List<GoodsResultVo> list = mapper.listByCarouselId(carouselId);
        Iterator<GoodsResultVo> iterator = list.iterator();
        while (iterator.hasNext()){
            GoodsResultVo next = iterator.next();
            if (next.getStock()==0){
                iterator.remove();
            }
        }
        return list;
    }

    /**
     * 根据SPUId更新商品的启用状态。
     *
     * @param spuId  商品的唯一标识符。
     * @param enable 1表示启用，0表示禁用。
     */
    private void updateEnableByspuId(Long spuId, int enable) {
        // 定义启用和禁用的文本描述
        String[] enableText = {"禁用", "启用"};
        // 记录日志，表示即将更改状态
        log.info("即将使商品{}的状态设置为:{}", spuId, enableText[enable]);
        // 根据SPUId查询商品信息
        GoodsVo select = mapper.select(spuId);
        // 检查商品是否存在
        if (select == null) {
            String msg = enableText[enable] + "商品失败,商品不存在";
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, msg);
        }
        // 检查商品状态是否已经为想要设置的状态，避免重复操作
        if (select.getEnable() == enable) {
            String msg = enableText[enable] + "商品失败,商品已处于" + enableText[enable] + "状态";
            throw new ServiceException(ServiceCode.ERR_BAD_REQUEST, msg);
        }
        // 准备更新的商品信息
        Goods goods = new Goods();
        goods.setSpuId(spuId);
        goods.setEnable(enable);
        int update = mapper.update(goods); // 执行更新操作
        // 检查更新操作是否成功
        if (update != 1) {
            String msg = enableText[enable] + "商品失败,服务器忙,请稍后重试";
            throw new ServiceException(ServiceCode.ERR_UPDATE_FAILED, msg);
        }
    }

}
